package com.neo.push.core.connection;

import com.neo.push.core.RegisterMessage;
import com.neo.push.core.TextMessage;
import io.netty.channel.ChannelHandlerContext;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by lock on 17-7-11.
 */
public abstract class AbstractSocketConnection implements SocketConnection {

    protected final ChannelHandlerContext ctx;
    private List<MessageAcceptor> acceptors;
    private ConnectionListener connectionListener;


    public AbstractSocketConnection(ChannelHandlerContext ctx,ConnectionListener listener) {
        this.ctx = ctx;
        this.connectionListener = listener;
    }


    @Override
    public String id() {
        return ctx.channel().id().asLongText();
    }


    /**
     * 收到了一个消息,并不能知道是哪种业务类型的消息，委托给消息处理器去处理
     * @param message
     */
    @Override
    public void acceptMessage(final TextMessage message) {
        try{
            MessageAcceptor acceptor = getAcceptor(message);
            acceptor.acceptedMessage(this, message);
        }catch (Exception ex){
            handleThrowable(ex);
        }
    }


    private MessageAcceptor getAcceptor(TextMessage message){
        if(null==acceptors){
            throw new RuntimeException(" not supported current message type !");
        }
        MessageAcceptor acceptor = null;
        for(MessageAcceptor a : acceptors){
            if(a.isSupported(message)){
                acceptor = a;
                break;
            }
        }
        if(null==acceptor){
            throw new RuntimeException(" not supported current message type !");
        }
        return acceptor;
    }

    /**
     * 添加消息处理器,connection接收的消息，发放给消息处理器处理
     * @param handler       添加支持的消息处理
     * @return              当前的连接
     */
    @Override
    public SocketConnection addMessageHandler(MessageAcceptor handler) {
        if(null==acceptors) this.acceptors = new ArrayList<>();
        this.acceptors.add(handler);
        return this;
    }

    @Override
    public ChannelHandlerContext ctx() {
        return ctx;
    }


    @Override
    public void close() {
        ctx.close();
        connectionListener.closed(this);
    }


    @Override
    public void register(RegisterMessage registerMessage) throws Exception {
        connectionListener.register(this,registerMessage);
    }



    @Override
    public void handleThrowable(Throwable throwable) {
        throwable.printStackTrace();
        close();
    }


}
